import { Request, Response } from 'express';
import { prisma } from '@/config/database';
import { logger } from '@/utils/logger';
import ApiError from '@/utils/ApiError';
import catchAsync from '@/utils/catchAsync';
import bcrypt from 'bcryptjs';
import { hasS3, uploadBufferToS3 } from '@/utils/s3';
import path from 'path';
import fs from 'fs';
import { promisify } from 'util';

const writeFile = promisify(fs.writeFile);
const mkdir = promisify(fs.mkdir);

export class UserController {
  // 获取当前用户信息
  getCurrentUser = catchAsync(async (req: Request, res: Response) => {
    const userId = (req as any).userId || (req as any).user?.id;

    const me = await prisma.user.findUnique({
      where: { id: userId },
      select: {
        id: true,
        username: true,
        email: true,
        displayName: true,
        nickname: true,
        avatar: true,
        bio: true,
        phone: true,
        birthday: true,
        isOnline: true,
        lastSeen: true,
        createdAt: true,
        updatedAt: true,
        partnerId: true
      }
    });

    if (!me) {
      throw new ApiError(404, '用户不存在');
    }

    let partner: any = null;
    if (me.partnerId) {
      partner = await prisma.user.findUnique({
        where: { id: me.partnerId },
        select: {
          id: true,
          username: true,
          displayName: true,
          nickname: true,
          avatar: true,
        }
      });
    }

    // 返回完整的用户信息，包括 partner 信息
    const userData = {
      ...me,
      partner
    };

    res.json({
      success: true,
      data: userData
    });
  });

  // 更新用户资料
  updateProfile = catchAsync(async (req: Request, res: Response) => {
    const userId = (req as any).userId;
    const { nickname, avatar } = req.body;

    const user = await prisma.user.update({
      where: { id: userId },
      data: {
        ...(nickname && { nickname }),
        ...(avatar && { avatar })
      },
      select: {
        id: true,
        username: true,
        nickname: true,
        avatar: true,
        isOnline: true,
        lastSeen: true
      }
    });

    res.json({
      success: true,
      data: user,
      message: '资料更新成功'
    });
  });

  // 上传头像
  uploadAvatar = catchAsync(async (req: Request, res: Response) => {
    const userId = (req as any).userId;
    const file = (req as any).file;

    if (!file) {
      throw new ApiError(400, '请选择头像文件');
    }

    // 检查文件类型
    if (!file.mimetype.startsWith('image/')) {
      throw new ApiError(400, '请选择图片文件');
    }

    // 检查文件大小 (5MB)
    if (file.size > 5 * 1024 * 1024) {
      throw new ApiError(400, '图片大小不能超过5MB');
    }

    let avatarUrl: string;

    try {
      // 优先使用 S3，如果没有配置则使用本地存储
      if (hasS3()) {
        const ext = (file.originalname.split('.').pop() || '').toLowerCase();
        const key = `avatars/${userId}/${Date.now()}_${Math.random().toString(36).slice(2)}.${ext || 'bin'}`;
        avatarUrl = await uploadBufferToS3(key, file.buffer, file.mimetype);
      } else {
        // 使用本地存储
        const ext = (file.originalname.split('.').pop() || '').toLowerCase();
        const filename = `${Date.now()}_${Math.random().toString(36).slice(2)}.${ext || 'bin'}`;
        const uploadDir = path.join(process.cwd(), 'uploads', 'avatars', userId);
        
        // 确保目录存在
        await mkdir(uploadDir, { recursive: true });
        
        const filePath = path.join(uploadDir, filename);
        await writeFile(filePath, file.buffer);
        
        // 返回相对URL路径
        avatarUrl = `/uploads/avatars/${userId}/${filename}`;
      }

      // 更新用户头像
      const user = await prisma.user.update({
        where: { id: userId },
        data: { avatar: avatarUrl },
        select: {
          id: true,
          username: true,
          nickname: true,
          avatar: true,
          isOnline: true,
          lastSeen: true
        }
      });

      res.json({
        success: true,
        data: user,
        message: '头像上传成功'
      });
    } catch (error: any) {
      logger.error('头像上传失败:', error);
      throw new ApiError(500, '头像上传失败');
    }
  });

  // 获取另一个用户信息（聊天对象）
  getOtherUser = catchAsync(async (req: Request, res: Response) => {
    const userId = (req as any).userId;
    
    const otherUser = await prisma.user.findFirst({
      where: {
        id: { not: userId }
      },
      select: {
        id: true,
        username: true,
        nickname: true,
        avatar: true,
        isOnline: true,
        lastSeen: true
      }
    });

    if (!otherUser) {
      throw new ApiError(404, '聊天对象不存在');
    }

    res.json({
      success: true,
      data: otherUser
    });
  });

  // 绑定关系：与目标用户名互相绑定，开启全量共享
  bindPartner = catchAsync(async (req: Request, res: Response) => {
    const userId = (req as any).userId || (req as any).user?.id;
    const { username } = req.body as { username: string };
    if (!username) {
      throw new ApiError(400, '缺少用户名');
    }
    const target = await prisma.user.findUnique({ where: { username }, select: { id: true, partnerId: true }});
    if (!target) throw new ApiError(404, '用户不存在');
    if (target.id === userId) throw new ApiError(400, '不能绑定自己');

    await prisma.$transaction(async (tx) => {
      const me = await tx.user.findUnique({ where: { id: userId }, select: { partnerId: true }});
      if (me?.partnerId) await tx.user.update({ where: { id: userId }, data: { partnerId: null }});
      if (target.partnerId) await tx.user.update({ where: { id: target.id }, data: { partnerId: null }});
      await tx.user.update({ where: { id: userId }, data: { partnerId: target.id }});
      await tx.user.update({ where: { id: target.id }, data: { partnerId: userId }});
    });

    res.json({ success: true, message: '绑定成功' });
  });

  // 解绑关系：解除全量共享
  unbindPartner = catchAsync(async (req: Request, res: Response) => {
    const userId = (req as any).userId || (req as any).user?.id;
    const me = await prisma.user.findUnique({ where: { id: userId }, select: { partnerId: true }});
    if (me?.partnerId) {
      await prisma.$transaction([
        prisma.user.update({ where: { id: userId }, data: { partnerId: null }}),
        prisma.user.update({ where: { id: me.partnerId }, data: { partnerId: null }})
      ]);
    }
    res.json({ success: true, message: '解绑成功' });
  });

  // 更新在线状态
  updateOnlineStatus = catchAsync(async (req: Request, res: Response) => {
    const userId = (req as any).userId;
    const { isOnline } = req.body;

    await prisma.user.update({
      where: { id: userId },
      data: {
        isOnline,
        lastSeen: isOnline ? undefined : new Date()
      }
    });

    res.json({
      success: true,
      message: '在线状态更新成功'
    });
  });

  // 修改密码
  changePassword = catchAsync(async (req: Request, res: Response) => {
    const userId = (req as any).userId;
    const { currentPassword, newPassword } = req.body;

    // 验证当前密码
    const user = await prisma.user.findUnique({
      where: { id: userId },
      select: { password: true }
    });

    if (!user) {
      throw new ApiError(404, '用户不存在');
    }

    const isCurrentPasswordValid = await bcrypt.compare(currentPassword, user.password);
    if (!isCurrentPasswordValid) {
      throw new ApiError(400, '当前密码错误');
    }

    // 加密新密码
    const hashedNewPassword = await bcrypt.hash(newPassword, 12);

    // 更新密码
    await prisma.user.update({
      where: { id: userId },
      data: { password: hashedNewPassword }
    });

    res.json({
      success: true,
      message: '密码修改成功'
    });
  });

  // 管理员：获取所有用户列表
  getAllUsers = catchAsync(async (req: Request, res: Response) => {
    const users = await prisma.user.findMany({
      select: {
        id: true,
        username: true,
        nickname: true,
        avatar: true,
        isOnline: true,
        lastSeen: true,
        createdAt: true,
        partnerId: true
      },
      orderBy: { createdAt: 'desc' }
    });

    res.json({
      success: true,
      data: users
    });
  });

  // 管理员：更新用户信息
  updateUser = catchAsync(async (req: Request, res: Response) => {
    const { userId } = req.params;
    const { username, nickname, avatar } = req.body;

    const user = await prisma.user.update({
      where: { id: userId },
      data: {
        ...(username && { username }),
        ...(nickname && { nickname }),
        ...(avatar && { avatar })
      },
      select: {
        id: true,
        username: true,
        nickname: true,
        avatar: true,
        isOnline: true,
        lastSeen: true,
        createdAt: true
      }
    });

    res.json({
      success: true,
      data: user,
      message: '用户信息更新成功'
    });
  });

  // 管理员：重置用户密码
  resetUserPassword = catchAsync(async (req: Request, res: Response) => {
    const { userId } = req.params;
    const { newPassword } = req.body;

    const hashedPassword = await bcrypt.hash(newPassword, 12);

    await prisma.user.update({
      where: { id: userId },
      data: { password: hashedPassword }
    });

    res.json({
      success: true,
      message: '密码重置成功'
    });
  });

  // 管理员：删除用户
  deleteUser = catchAsync(async (req: Request, res: Response) => {
    const { userId } = req.params;

    await prisma.user.delete({
      where: { id: userId }
    });

    res.json({
      success: true,
      message: '用户删除成功'
    });
  });
}

export const userController = new UserController();